#include "head_s.h"

int upload(const user_t* status,const portocol_t* portocol, int net_fd, MYSQL *mysql)
{

    // 拼接目标文件虚拟路径, 和获取当前工作路径
    char path_s[1024] = {0};
    char dir_path[124] = {0};
    int len_path = strlen(status->path);

    char base_path[100] = {0};
    getparameter("base_path", base_path);

    sprintf(path_s,"%s%s", status->path, status->arg);
    sprintf(dir_path, "%s", status->path);
    LOG_WRITE(LOG_INFO, "len_path : %d\n", len_path);
    if(len_path != 1){
        dir_path[len_path-1] = '\0';
    }
    LOG_WRITE(LOG_DEBUG, "当前工作路径为：%s\n", status->path);
    LOG_WRITE(LOG_INFO, "path_s : %s\n", path_s);
    LOG_WRITE(LOG_INFO, "dir_pats : %s\n", dir_path);

    //判断文件是否打开成功
    char is_open[10] = {0};
    recv(net_fd, is_open, 1, MSG_WAITALL);
    if (strcmp(is_open, "1") == 0)
    {
        return -1;
    }

    // 读取文件大小
    off_t file_size = 0;
    int ret_len = recv(net_fd, &file_size, sizeof(off_t), MSG_WAITALL);
    if(ret_len == -1){
        perror("recv filename_len failed!\n");
        return -1;
    }

    int len = 0;
    char hash[1024] = {0};
    recv(net_fd, &len, sizeof(int), MSG_WAITALL);
    recv(net_fd, hash, len, MSG_WAITALL);



    //获取下载路径 (文件名为hash值)
    char path[1024] = {0};
    sprintf(path, "%s%s",base_path, hash);


    // TODO 1:这个文件已经存在， 大小形同
    //         -》 告诉客户端， 不用传了
    // TODO 2: 这个文件存在， 比这个大小小
    //      -》 断点续传
    // TODO 3， 这个文件不存在
    //       -》 传全新文件

    int flag = -1;// 0全新上传，  1：重名文件  2 断点续传  3.急速妙传



    int flag_y = -1;//断点传输后是否存入数据-->0不存，1存, 2,同用户同路径断点续传，不存数据
    int flag_hash = -1; //同路径是否有哈希相同的文件 0:无 1:有
    char hash_f[1024] = {0};
    int x = 0;//是否有重名
    int file_fd = open(path, O_RDWR);//遍历有无哈希->文件是否存过

    int u_id;
    //获取user_id
    char user_id[10] = {0};
    char buf1[1024] = {0};
    sprintf(buf1, "select id from user_info where name ='%s'", status->user_name);

    mysql_query(mysql, buf1);
    MYSQL_RES *res1 = mysql_store_result(mysql);
    MYSQL_ROW row1 = mysql_fetch_row(res1);
    strncpy(user_id, row1[0], sizeof(user_id)-1);
    mysql_free_result(res1);

    u_id = atoi(user_id);

    //获取p_id
    int pid = 0;
    char p_id[10] = {0};
    char buf[1024] ={0};


    sprintf(buf, "select id from file_info where user_id = %d and file_path = '%s' and file_type = 1", u_id, dir_path);


    mysql_query(mysql, buf);
    MYSQL_RES *res = mysql_store_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(res);
    strncpy(p_id, row[0], sizeof(row[0])-1);

    pid = atoi(p_id);

    mysql_free_result(res);


    //当前路径下有无同名文件 , 若有记录哈希
    char buf4[1024] = {0};
    char file_hash_1[1024] = {0};//同名哈希
    char file_path[1024] = {0};//同目录同哈希路径

    sprintf(buf, "select file_hash from file_info where user_id = %d and p_id = %d and file_path = '%s' and file_type = 2 and exist_flag = 0", u_id, pid, path_s);
    mysql_query(mysql, buf);
    MYSQL_RES *res4 = mysql_store_result(mysql);

    printf("有无重名文件：");

    if( res4 != NULL && mysql_num_rows(res4)>0 ){
        printf("有\n");
        x=1;
        MYSQL_ROW row4 = mysql_fetch_row(res4);
        strncpy(file_hash_1, row4[0], sizeof(row4[0]) - 1);

    }
    if(x != 1){
        x = 0;
        printf("无\n");
    }
    mysql_free_result(res4);
    int sum = strcmp(hash, file_hash_1);//对比哈希， 是否是同一文件-> 0：相同  非0：不同


    char buf2[1024] = {0};
    int ret;

    if(file_fd > 0){
        //遍历当前目录哈希, 若有相同，记录路径
        sprintf(buf2, "select file_hash, file_path from file_info where user_id = %d and p_id = %d and file_type = 2 and exist_flag = 0", u_id, pid);

        mysql_query(mysql, buf2);
        MYSQL_RES *res2 = mysql_store_result(mysql);
        ret = mysql_num_rows(res2);
        if(res2 != NULL && ret != 0){

            MYSQL_ROW row2;
            while((row2 = mysql_fetch_row(res2))){
                if(strcmp(hash, row2[0]) == 0) {
                    flag_hash = 1;

                }
            }
        }
        if(flag_hash == -1){
            flag_hash = 0;
        }
        mysql_free_result(res2);
    }

    //已存文件大小
    int n = 0;

    //有该哈希
    if(file_fd > 0){

        struct stat file_st;
        fstat(file_fd, &file_st);
        n = file_st.st_size;

        if(file_size == n) { //文件传输完毕
            if(x == 1){//有同名
                if(sum == 0){//有该哈希，大小相同，有同名，哈希值相同 --> 同名文件
                    flag = 1;
                }else{////有该哈希，大小相同，有同名，哈希值不同--》同名文件
                    flag = 1;
                }
            }else{//无同名
                //无同名则实现急速秒传；
                flag = 3;
            }
        }else{//未传输完毕 ，断点续传判断是否时同目录下断点续传
            if(x == 1) {//有同名
                if(sum == 0){//同目录下断点续传-->断点传续后不存入数据
                    flag = 2;
                    flag_y = 2;
                }else {//同名文件哈希不同
                    if(flag_hash == 1){ //同路径有哈希相同文件有同名-->断点续传后不存数据
                        flag = 2;
                        flag_y = 0;
                    }else{    // 同路径没有哈希相同文件有同名-->断点续传后不存数据
                        flag = 2;
                        flag_y = 0;
                    }
                }
            }else {//无同名
                if(flag_hash == 1){//无同名文件，同路径下有该hash-->断点续传后存入数据
                    flag = 2;
                    flag_y = 1;
                }else{//同路径下无该哈希，无同名-->断点续传后存入数据
                    flag = 2;
                    flag_y = 1;
                }
            }
        }
    }else { //无该哈希
        if(x == 1){
            flag = 1;
        }else{
            flag = 0;
        }
    }


    //传出参数
    send(net_fd, &flag, sizeof(int), MSG_NOSIGNAL);
    send(net_fd, &flag_y, sizeof(int), MSG_NOSIGNAL);


    // TODO: ------------------------------
    // 打开文件
    if(flag == 0){
        // 全新上传
        int file_fd2 = open(path, O_RDWR|O_CREAT, 0600);

        ftruncate(file_fd2, file_size);
        void* mapped = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, file_fd2, 0);
        int ret = recv(net_fd, mapped, file_size, MSG_WAITALL);
        munmap(mapped, file_size );
        close(file_fd2);

        char buf3[1024] = {0};
        sprintf(buf3, "insert into file_info values(NULL, '%s', %d, %d, '%s', 2, '%s', 0)", status->arg, u_id, pid, path_s, hash);
        mysql_query(mysql, buf3);
        if(ret == file_size){
            LOG_WRITE(LOG_INFO, "全新上传成功");
        }else{
            LOG_WRITE(LOG_INFO, "文件未传输完毕");

        }
    }
    if(flag == 2){
        int file_fd2 = open(path, O_RDWR);
        // 断点上传
        off_t upload_size = n;
        send(net_fd, &upload_size, sizeof(off_t), MSG_NOSIGNAL);
        ftruncate(file_fd2, file_size);
        void* mapped = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, file_fd2,0);
        int ret = recv(net_fd, mapped+upload_size, file_size - upload_size, MSG_WAITALL);
        munmap(mapped, file_size);
        close(file_fd2);
        if((ret+n) != file_size){
            LOG_WRITE(LOG_INFO, "文件未存储完");
        }
        if(flag_y == 1){
            char buf3[1024] = {0};
            sprintf(buf3, "insert into file_info values(NULL, '%s', %d, %d, '%s', 2, '%s', 0)", status->arg, u_id, pid, path_s, hash);
            mysql_query(mysql, buf3);
            LOG_WRITE(LOG_INFO, "文件存储完毕完毕");
        }
    }

    if(flag == 3){
        char buf3[1024] = {0};
        sprintf(buf3, "insert into file_info values(NULL, '%s', %d, %d, '%s', 2, '%s', 0)", status->arg, u_id, pid, path_s, hash);
        mysql_query(mysql, buf3);
        LOG_WRITE(LOG_INFO, "急速秒传");
    }

    return 0;
}

